package com.starleague.hexagonal.flat.android;

import android.content.res.Resources;
import android.util.Log;

import com.starleague.battletech.android.R;
import com.starleague.hexagonal.IHexCoordinate;
import com.starleague.hexagonal.ImmutableHexCoordinate;
import com.starleague.hexagonal.android.IHexGridMetrics;
import com.starleague.hexagonal.flat.IFlatHexGrid;

public class FlatHexGridMetrics
        implements IHexGridMetrics
{
    private final IFlatHexGrid flatHexGrid;
    private double hexWidthBase;
    private double hexHeightBase;
    private double hexElevationHeightBase;
    private double scale = 1;

    private int hexWidth;
    private int hexHeight;
    private int hexElevationHeight;

    private int hexGridWidth;
    private int hexGridHeight;

    private int hexQuarterWidth;
    private int hexThreeQuartersWidth;
    private int hexHalfWidth;
    private int hexHalfHeight;

    public FlatHexGridMetrics(IFlatHexGrid flatHexGrid, Resources resources)
    {
        this.flatHexGrid = flatHexGrid;

        // TODO: Get resource info (HexWidth/Height) from some sort of wrapper
        this.hexWidthBase = resources.getDimension(R.dimen.hex_bitmap_width);
        this.hexHeightBase = resources.getDimension(R.dimen.hex_bitmap_height);
        this.hexElevationHeightBase = resources.getDimension(R.dimen.hex_elevation_height);

        recalculateSizes();
    }

    @Override
    public double getScale()
    {
        return this.scale;
    }

    @Override
    public void setScale(double scale)
    {
        this.scale = scale;

        recalculateSizes();
    }

    @Override
    public int getHexWidth()
    {
        return this.hexWidth;
    }

    @Override
    public int getHexQuarterWidth()
    {
        return this.hexQuarterWidth;
    }

    @Override
    public int getHexThreeQuartersWidth()
    {

        return this.hexThreeQuartersWidth;
    }

    @Override
    public int getHexHeight()
    {
        return this.hexHeight;
    }

    @Override
    public int getHexHalfHeight()
    {
        return this.hexHalfHeight;
    }

    @Override
    public int getHexElevationHeight()
    {
        return this.hexElevationHeight;
    }

    @Override
    public int getHexGridWidth()
    {
        return this.hexGridWidth;
    }

    @Override
    public int getHexGridHeight()
    {
        return this.hexGridHeight;
    }

    @Override
    public int getHexTop(IHexCoordinate hexCoordinate)
    {
        return this.hexHeight
               * hexCoordinate.getGridY()
               + this.hexHalfHeight
               * ((hexCoordinate.getGridX() + 1) % 2);
    }

    @Override
    public int getHexLeft(IHexCoordinate hexCoordinate)
    {
        return this.hexThreeQuartersWidth * hexCoordinate.getGridX();
    }

    @Override
    public IHexCoordinate getHexCoordinateAtPoint(int gridPointX,
                                                  int gridPointY)
    {
        int approxGridPointX = (int) ((double) (gridPointX - this.hexHalfWidth) / (double) this.hexThreeQuartersWidth);
        int approxGridPointY = (int) ((double) (gridPointY + this.hexHalfHeight) / (double) this.hexHeight);

        // Log.w("INFO", "getHexCoordinateAtPoint: APPROX X = " +
        // approxGridPointX);
        // Log.w("INFO", "getHexCoordinateAtPoint: APPROX Y = " +
        // approxGridPointY);

        double minDistance = Double.MAX_VALUE;
        int closestGridX = Integer.MAX_VALUE;
        int closestGridY = Integer.MAX_VALUE;

        for (int gridX = approxGridPointX - 1; gridX <= approxGridPointX + 1; ++gridX)
            for (int gridY = approxGridPointY - 2; gridY <= approxGridPointY + 2; ++gridY)
            {
                double centerX = this.hexThreeQuartersWidth * gridX + this.hexHalfWidth;
                double centerY = this.hexHeight
                                 * gridY
                                 + this.hexHalfHeight
                                 * ((gridX + 1) % 2)
                                 + this.hexHalfHeight;

                double distanceX = gridPointX - centerX;
                double distanceY = gridPointY - centerY;
                double distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
                // Log.w("INFO", "getHexCoordinateAtPoint: DIST [" + gridX +
                // ", " + gridY
                // + "] = " + distance);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    closestGridX = gridX;
                    closestGridY = gridY;
                }
            }

        // Log.w("INFO", "getHexCoordinateAtPoint: SEL HEX ["
        // + closestGridX
        // + ", "
        // + closestGridY
        // + "] = "
        // + minDistance);

        return new ImmutableHexCoordinate(closestGridX, closestGridY);
    }

    private void recalculateSizes()
    {
        this.hexWidth = (int) (this.hexWidthBase * this.scale);
        this.hexHeight = (int) (this.hexHeightBase * this.scale);
        this.hexElevationHeight = (int) (this.hexElevationHeightBase * this.scale);

        this.hexQuarterWidth = this.hexWidth / 4;
        this.hexThreeQuartersWidth = this.hexWidth * 3 / 4;// - (this.hexWidth / 4);
        this.hexHalfWidth = this.hexWidth / 2;
        this.hexHalfHeight = this.hexHeight / 2;

        this.hexGridWidth = (this.flatHexGrid.getNumHexesX() - 1)
                            * this.hexThreeQuartersWidth
                            + this.hexWidth;
        this.hexGridHeight = this.flatHexGrid.getNumHexesY() * this.hexHeight + this.hexHalfHeight;

        Log.w("INFO", "HEX SIZE: " + this.hexWidth + ", " + this.hexHeight);
        Log.w("INFO", "GRID SIZE: " + this.hexGridWidth + "," + this.hexGridHeight);
    }
}
